#include "graphwidget.h"

#include <limits>

#include "cashplusplus.h"

const qreal GraphWidget::MARGIN = 10.0;
const qreal GraphWidget::FONT_BASE = 15.0;
const qreal GraphWidget::FONT_HEIGHT_DIVIDER = 100.0;
const int GraphWidget::ALIGN_LEFT = Qt::AlignLeft | Qt::AlignVCenter;
const int GraphWidget::ALIGN_RIGHT = Qt::AlignRight | Qt::AlignVCenter;

const QPen GraphWidget::LINE_PEN = QPen(QBrush(QColor(100, 160, 70)), 5.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
const QPen GraphWidget::TEXT_PEN = QPen(QColor(190, 190, 190));

GraphWidget::GraphWidget(QWidget* parent)
	: QFrame(parent)
{
}

void GraphWidget::setData(const QList<QPair<uint, double> >& data)
{
	m_data = data;

	update();
}

void GraphWidget::paintEvent(QPaintEvent* event)
{
	uint beginTime = std::numeric_limits<uint>::max();
	uint endTime = std::numeric_limits<uint>::min();

	double minBalance = 0.0;
	double maxBalance = std::numeric_limits<double>::min();

	QPair<uint, double> point;
	foreach (point, m_data)
	{
		if (point.first < beginTime)
			beginTime = point.first;

		if (point.first > endTime)
			endTime = point.first;

		if (point.second < minBalance)
			minBalance = point.second;

		if (point.second > maxBalance)
			maxBalance = point.second;
	}

	qreal timeRange = endTime - beginTime;
	qreal moneyRange = maxBalance - minBalance;

	if (timeRange == 0.0)
	{
		timeRange = 1.0;
	}

	if (moneyRange == 0.0)
	{
		moneyRange = 1.0;
	}

{ // Scope painter
	QPainter painter(this);
	painter.setRenderHint(QPainter::Antialiasing, true);

	QRectF bounds = rect();

	painter.fillRect(bounds, Qt::white);

	qreal fontSize = FONT_BASE + bounds.height() / FONT_HEIGHT_DIVIDER;

	QFont font;
	font.setBold(true);
	font.setPixelSize(fontSize);

	painter.setFont(font);
	painter.setPen(TEXT_PEN);

	qreal effectiveWidth = bounds.width() - 2 * MARGIN;
	qreal effectiveHeight = bounds.height() - 2 * MARGIN;

	if (m_data.size() > 0)
	{
		QRectF timeRect(MARGIN, bounds.height() - MARGIN - fontSize, effectiveWidth, fontSize);
		QRectF halfMoneyRect(MARGIN, bounds.height() / 2 - fontSize / 2, effectiveWidth, fontSize);
		QRectF maxMoneyRect(MARGIN, MARGIN, effectiveWidth, fontSize);

		// Time labels
		painter.drawText(timeRect, ALIGN_LEFT, QDateTime::fromTime_t(beginTime).toString("MM/dd/yyyy"));
		painter.drawText(timeRect, ALIGN_RIGHT, QDateTime::fromTime_t(endTime).toString("MM/dd/yyyy"));

		// Money labels
		painter.drawText(maxMoneyRect, ALIGN_LEFT,  QString("$%L1").arg(maxBalance, 0, 'f', 2).replace("$-", "-$"));
		painter.drawText(halfMoneyRect, ALIGN_LEFT, QString("$%L1").arg((minBalance + maxBalance) / 2, 0, 'f', 2).replace("$-", "-$"));

		painter.setViewport(0, bounds.height(), bounds.width(), -bounds.height());

		if (!CashPlusPlus::compareDoubles(minBalance, 0.0) && minBalance < 0.0)
		{
			qreal y = -minBalance / moneyRange;
			painter.drawLine(MARGIN, MARGIN + y * effectiveHeight, MARGIN + effectiveWidth, MARGIN + y * effectiveHeight);
		}

		painter.setPen(LINE_PEN);
		for (int i = 0; i < m_data.size() - 1; ++i)
		{
			QPair<uint, double> pair1 = m_data.at(i);
			QPair<uint, double> pair2 = m_data.at(i + 1);

			qreal x1 = (pair1.first - beginTime) / timeRange;
			qreal y1 = (pair1.second - minBalance) / moneyRange;

			qreal x2 = (pair2.first - beginTime) / timeRange;
			qreal y2 = (pair2.second - minBalance) / moneyRange;

			QPointF p1 = QPointF(MARGIN + x1 * effectiveWidth, MARGIN + y1 * effectiveHeight);
			QPointF p2 = QPointF(MARGIN + x2 * effectiveWidth, MARGIN + y2 * effectiveHeight);

			painter.drawLine(p1, p2);
		}
	}
	else
	{
		painter.drawText(bounds, Qt::AlignCenter | Qt::AlignVCenter, "No Transaction Data");
	}
}

	QFrame::paintEvent(event);
}
